package com.example.birdfriends.controller;

import cn.hutool.core.io.FileTypeUtil;
import com.example.birdfriends.pojo.post.Post;
import com.example.birdfriends.pojo.post.PostFront;
import com.example.birdfriends.pojo.post.PostsAndAuthors;
import com.example.birdfriends.pojo.recommend.Recommend;
import com.example.birdfriends.pojo.user.InfoInMainPage;
import com.example.birdfriends.pojo.user.User;
import com.example.birdfriends.service.*;
import com.example.birdfriends.utils.convert.ConvertService;
import com.example.birdfriends.utils.files.FileService;
import com.example.birdfriends.utils.post.PostUtil;
import com.example.birdfriends.utils.recommend.RecommendUtil;
import com.example.birdfriends.utils.result.Result;
import com.example.birdfriends.utils.sort.Sort;
import javafx.geometry.Pos;
import jdk.nashorn.internal.ir.LoopNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.jws.soap.SOAPBinding;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@RequestMapping("/post")
public class PostController {
    @Autowired
    private PostService postService = null;
    @Autowired
    private UserService userService = null;
    @Autowired
    private ConvertService convertService = null;
    @Autowired
    private FileService fileService = null;
    @Autowired
    private Result result = null;

    private List<String> imagePathList = new ArrayList<>();
    private List<String> videoPathList = new ArrayList<>();
    private Long pid = null;  // 当前帖子id
    private Post post = null;

    // 上传图片、视频文件
    @PostMapping("/upload")  // 用时间也不合适，因为同一时间会有不同用户创建出不同的帖子
    public String uploadImagesOrVideos(MultipartFile file) throws IOException {
        InputStream stream = file.getInputStream();  // 获取文件的输入流
        String type = FileTypeUtil.getType(stream);
        List<String> imageTypes = fileService.imageTypes();
        List<String> videoTypes = fileService.videoTypes();

        String originalFilename = file.getOriginalFilename();
        String imagePath = "D:/bf-files/springboot-upload/post-files/post-images/post-"+pid+"/";
        String videoPath = "D:/bf-files/springboot-upload/post-files/post-videos/post-"+pid +"/";

        File parentImageFolder = new File(imagePath);
        File parentVideoFolder = new File(videoPath);
        if(!parentImageFolder.exists()) parentImageFolder.mkdirs();
        if(!parentVideoFolder.exists()) parentVideoFolder.mkdirs();
        if(imageTypes.contains(type)){
            // 上传的文件是图片
            File saveFile = new File(imagePath + originalFilename);
            file.transferTo(saveFile);

            // 图片文件的完整路径和名称
            String filePath = "http://localhost:8888/post-files/post-images/post-"+pid+"/"+originalFilename;
            if(imagePathList == null) {
                imagePathList = new ArrayList<>();
                imagePathList.add(filePath);
            }
            else this.imagePathList.add(filePath);
        }else if(videoTypes.contains(type)){
            File saveFile = new File(videoPath + originalFilename);
            file.transferTo(saveFile);
            String filePath = "http://localhost:8888/post-files/post-videos/post-"+pid+"/"+originalFilename;
            if (this.videoPathList == null) {
                this.videoPathList = new ArrayList<>();
                this.videoPathList.add(filePath);
            }
            else this.videoPathList .add(filePath);
        }else {
            return "非法的文件格式";
        }

        // 现在将图片列表和视频列表保存到数据库
//        this.post.printPost();
        this.post.setImages(convertService.list2String(this.imagePathList));
        this.post.setVideos(convertService.list2String(this.videoPathList));

        int update = postService.setImagesAndVideos(this.post);
        return update > 0 ? "文件上传成功" : "文件上传失败";
    }

    // 发布帖子：服务器设置创建时间，此时不设置图片、视频url
    @PostMapping("/create")  // 当前用户要发布一篇帖子，只需要当前用户的id
    public Map<String, Object> createPost(@RequestBody Post post){
        // 每次创建一个帖子时先把图片和视频url设为null
        this.imagePathList = new ArrayList<>();
        this.videoPathList = new ArrayList<>();
        // 判断当前是否有用户登录
        if(post.getUid() == null){
            return result.resultMap(false, "游客无法发布帖子，请先登录", null);
        }
        // 现有的用户id列表
        List<Long> userIds = userService.findAllUserIds();
        // 用户发表帖子，用户上传数据中
        Long uid = post.getUid();
        if(!userIds.contains(uid)){
            // 当前传入的用户id不为已有的用户id，不可以创建帖子
            return result.resultMap(false, "用户不存在，请先创建用户", null);
        }
        // 时间以服务器时间为准
        post.setCreateAt(new Timestamp(System.currentTimeMillis()));
//        post.setCreateAt(new Date());

        int create = postService.createPost(post);
        pid = post.getPid();
        this.post = postService.findPostByPid(pid);

        boolean success = create > 0;
        String msg = success ? "发布成功" : "发布失败";

        return result.resultMap(success, msg, post);
    }

    // 用户修改帖子：可能修改（主题，内容，视频，图片），其他不动
    @PostMapping("/update")
    public Map<String, Object> updatePost(@RequestBody PostFront postFront) throws ParseException {
        Long pid = postFront.getPid();  // 当前帖子的id
        Long curLoginUid = postFront.getCurLoginUid();  // 当前登录的用户id，因为当前登录的用户会对帖子进行一系列操作
        String curPage = postFront.getCurPage();
        // 帖子必须发布人才能修改：根据帖子id查找用户id，比较两个id是否相同
        // 当前登录的用户id与post的作者id一致才可修改
        boolean isAuthor = postService.compareUid(pid, curLoginUid);
        if(!isAuthor){
            return result.resultMap(false, "非本文作者不可修改", null);
        }
        Post currentPost = convertService.postFront2Post(postFront);  // 将postFront转化成持久化到数据库的post
        System.out.print("修改帖子文本:");currentPost.printPost();

        // 允许用户修改：根据pid查找对应数据项--将post中非空字段填补--修改数据库对应数据项
        Post originalPost = postService.findPostByPid(pid);
        System.out.print("数据库中的原始post："); originalPost.printPost();
        originalPost.setTitle(currentPost.getTitle());
        originalPost.setTheme(currentPost.getTheme());
        originalPost.setContent(currentPost.getContent());System.out.print("修改后的post：");originalPost.printPost();
        // 先不管文件
        int update = postService.updatePostByPid(originalPost);
        boolean success = update > 0;
        if (success){
            PostFront ans = convertService.post2PostFront(originalPost, curLoginUid, curPage);
            return result.resultMap(true, "更新成功", ans);
        }

        return result.resultMap(false, "更新失败", null);
    }

    // 删除帖子：比较当前用户id和帖子作者id是否一致，一致才可删除
    @PostMapping("/delete")
    public Map<String, Object> deletePost(@RequestBody PostFront postFront){
        Long pid = postFront.getPid();
        String curPage = postFront.getCurPage();
        Long curLoginUid = postFront.getCurLoginUid();
        if(!postService.compareUid(pid, curLoginUid)){
            return result.resultMap(false, "非本文作者，不可删除", null);
        }

        int delete = postService.deletePostByPid(pid);
        boolean success = delete > 0;
        if(!success){
            return result.resultMap(false, "删除失败", null);
        }

        // 要想删除帖子，只能在用户详情界面的帖子列表中删除，所以此时的用户肯定是帖子作者，只需要根据当前帖子作者
        List<Post> posts = postService.findPostsByUid(curLoginUid);
        List<PostFront> postFrontList = new ArrayList<>();
        for (Post post : posts) {
            PostFront front = convertService.post2PostFront(post, curLoginUid, curPage);

            postFrontList.add(front);
        }
        return result.resultMap(true, "删除成功", postFrontList);
    }

    @PostMapping("/queryUserPosts")  // 用户详情页的帖子列表
    public Map<String, Object> queryUserPosts(@RequestBody User user){
        Long uid = user.getId();  // 当前登录的用户id
        // 通过用户id查询当前用户所发布的所有帖子
        List<Post> posts = postService.findPostsByUid(uid);
        boolean success = (posts != null) && (posts .size() > 0);

        if (success){
            List<PostFront> postFronts = convertService.posts2PostFronts(posts, uid, "userDetail");
            return result.resultMap(true, "检索成功", postFronts);
        }

        return result.resultMap(false, "检索失败", null);
    }

    private final long lineNumber = 50L;

    @PostMapping("loadPostsNotLogin")
    public Map<String, Object> loadPostsNotLogin(@RequestBody Long curPageNumber){
        // 无用户登录状态下加载帖子
        long start = (curPageNumber - 1) * lineNumber;
        List<Post> posts = postService.queryAllPosts(start, lineNumber);
        Long totalPostNumber = postService.countPostsNotLogin();
        PostsAndAuthors postsAndAuthors = convertService.findPostsAuthors(posts, null, "main");  // 当前无用户登录，传递的用户id为null
        postsAndAuthors.setTotalPostNumber(totalPostNumber);

        boolean success = posts != null && posts.size() > 0;
        if(success){
            return result.resultMap(true, "获取帖子数据成功", postsAndAuthors);
        }
        return result.resultMap(false, "获取帖子数据失败", postsAndAuthors);
    }

    // 用户登录状态下查询推荐栏帖子
    @PostMapping("/loadPostWithLogin")
    public Map<String, Object> loadPostsWithLogin(@RequestBody PostFront postFront){
        Long curLoginUid = postFront.getCurLoginUid();  // 当前登录的用户id
        Long curPageNumber = postFront.getCurPageNumber();  // 当前页号
        System.out.println("当前登录用户id："+curLoginUid+"; 当前页号："+curPageNumber);

        long start = (curPageNumber - 1) * this.lineNumber;
        List<Post> posts = new ArrayList<>();
        // 登录的用户，系统先查找推荐表有无对应的数据项
        Recommend recommend = recommendService.findRecommendByCurLoginUid(curLoginUid);
        if (recommend != null){
//            System.out.println("从recommend中检索帖子");
            // 给当前登录的用户的推荐存在，取出推荐
            int endIndex = (int)(start + lineNumber);  // 子列表结尾位置
            List<String> recommendPidList = convertService.string2List(recommend.getPidList());
            if (endIndex > recommendPidList.size()){
                // 最后一位大于我们列表的大小
                endIndex = recommendPidList.size();
            }
            List<String> subRecommendPidList = recommendPidList.subList((int)start, endIndex);  // 获取子列表

            for (String pid: subRecommendPidList) {
                posts.add(postService.findPostByPid(Long.parseLong(pid)));
            }
        }else {
            System.out.println("从post数据表中检索");
            // 推荐表中没有当前用户的数据项，直接取出posts表中的数据展示
            posts = postService.queryPostWithLoginInMain(curLoginUid, start, lineNumber);
        }
        long totalPostNumber = postService.countPostsWithLogin(curLoginUid);  // 总的贴子数
//        System.out.println("查询到的帖子数："+posts.size()+"; 总的帖子数:"+totalPostNumber);

        PostsAndAuthors postsAndAuthors = convertService.findPostsAuthors(posts, curLoginUid, "main");  // 找出非当前登录者发布的帖子即这些帖子的作者
        postsAndAuthors.setTotalPostNumber(totalPostNumber);
        boolean success = posts.size() > 0;
        if(success){
            return result.resultMap(true, "查询帖子成功", postsAndAuthors);
        }

        return result.resultMap(false, "查询帖子失败", postsAndAuthors);
    }

    @PostMapping("/hot")
    public Map<String, Object> loadHotPosts(@RequestBody User user){
        // 加载热门贴
        Long curLoginUid = user.getId();
        List<Post> posts = postService.findHotPostIdList();
        if (posts != null && !posts.isEmpty()){
            PostsAndAuthors postsAndAuthors = convertService.findPostsAuthors(posts, curLoginUid, "main");
            return result.resultMap(true, "检索成功", postsAndAuthors);
        }

        return result.resultMap(false, "暂无热帖哦，请稍后再来查看", null);
    }

    @Autowired
    private RecommendUtil recommendUtil;

    @PostMapping("/author")
    public Map<String, Object> findPostAuthor(@RequestBody PostFront postFront){
        Long uid = postFront.getAuthorId();  // 获取当前帖子作者id
        User user = userService.findUserByUid(uid);
        boolean success = user != null;
        if(success){
            user.setPassword("");
            return result.resultMap(true, "查询用户成功", user);
        }

        return result.resultMap(false, "查询用户失败", null);
    }

    @Autowired
    private FollowService followService = null;

    @Autowired
    private RecommendService recommendService;
    @PostMapping("/cf")  // 协同过滤找到用户可能想看的帖子
    public void cf(@RequestBody User user){
        System.out.println("collaborative filter");
        Long curLoginUid = user.getId();
        Recommend recommend = recommendService.findRecommendByCurLoginUid(curLoginUid);
        List<Long> recommendPidList = recommendUtil.collaborativeFilter(curLoginUid);  // 新的推荐帖子id列表,将要置顶的帖子id存入数据库

        if (recommend != null){
            System.out.println("修改已有的推荐");
            // 已经存在给当前用户的推荐列表，那么需要修改
            recommend.setPidList(convertService.list2String(recommendPidList));
            recommendService.updateRecommendPidList(recommend);
        }else {
            System.out.println("新增推荐");
            // 还没有给当前用户的推荐列表，创建一个数据项作为给用户的推荐
            Recommend recommend1 = new Recommend();
            recommend1.setPidList(convertService.list2String(recommendPidList));
            recommend1.setUid(curLoginUid);
            recommendService.insertRecommend(recommend1);
        }
    }

    @PostMapping("/loadFollowPost")
    public Map<String, Object> findMyFollowPosts(@RequestBody PostFront postFront){  // 此时传入的用户是当前登录的用户
        // 查找所有当前用户所关注的用户所发布的帖子
        Long curLoginUid = postFront.getCurLoginUid();  // 当前登录的用户的id
        Long curPageNumber = postFront.getCurPageNumber();

        List<Long> followedUids = followService.findFollowedUidsByCurUid(curLoginUid);  // 当前登录用户所关注的用户的id列表
        // 找出当前用户所关注的用户id
        PostsAndAuthors postsAndAuthors = postUtil.findMyFollowUsersAndPosts(followedUids, curLoginUid);

        boolean success = (followedUids != null) && !(followedUids.isEmpty());
        if(success){
            String message = "查询关注用户帖子成功";
            if(postsAndAuthors.getPostList().isEmpty()) message = "还没有关注";
            return result.resultMap(true, message, postsAndAuthors);
        }
        return result.resultMap(false, "还没有关注", postsAndAuthors);
    }

    @Autowired
    private Sort sort = null;
    @Autowired
    private PostUtil postUtil;

    @PostMapping("/loadPostsByTheme")
    public Map<String, Object> findPostsByTheme(@RequestBody InfoInMainPage info){
       // 当前的主题，根据当前是否由用户登录有不同查询
        User curLoginUser = info.getCurLoginUser();
//        System.out.print("当前登录用户");curLoginUser.printUser();
        String theme = info.getPostTheme();
        Long curPageNumber = info.getCurPageNumber();

        long start = (curPageNumber - 1) * this.lineNumber;

        if(curLoginUser == null){
            // 当前无用户登录
//            System.out.println("无用户登录："+postTheme);
            List<Post> posts = postService.findPostsByThemeNotLogin(theme, start, lineNumber);
            PostsAndAuthors postsAndAuthors = convertService.findPostsAuthors(posts, null, "main");
            Long totalPostNumber = postService.countPostByThemeNotLogin(theme);
            postsAndAuthors.setTotalPostNumber(totalPostNumber);

            boolean success = posts != null && !posts.isEmpty();
            if(success){
                return result.resultMap(true, "查询"+theme+"帖子成功", postsAndAuthors);
            }
            return result.resultMap(false, "暂无"+theme+"主题帖子", postsAndAuthors);
        }else {
            Long curLoginUid = curLoginUser.getId();
//            System.out.println("当前登录用户："+curLoginUid+"；当前页："+curPageNumber+"；主题："+theme);

            List<Post> posts = postService.findPostsByThemeWithLogin(theme, curLoginUid, start, lineNumber);
            PostsAndAuthors postsAndAuthors = convertService.findPostsAuthors(posts, curLoginUid, "main");
            Long totalPostNumber = postService.countPostByThemeWithLogin(theme, curLoginUid);
            postsAndAuthors.setTotalPostNumber(totalPostNumber);

            boolean success = posts != null && !posts.isEmpty();
            if(success){
                return result.resultMap(true, "查询"+theme+"帖子成功", postsAndAuthors);
            }
            return result.resultMap(false, "暂无"+theme+"主题帖子", postsAndAuthors);
        }
    }
}
